/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "节点树.h"
#include "节点数据声明.h"

//#include <pthread.h>
//#include<thr/threads.h>
#include <map>

#include <JIT.h>
#include <future>
#include <time.h>
#include <ppl.h>

#include <场景/场景.h>
#include <文件/file_文件名数据.h>
#include <core/引擎配置.h>
#include <Context/当前默认操作数据.h>


//#pragma comment(lib, "libpthread-static.lib")
static std::map<std::wstring, C_节点树*> g_节点树;
//static bool							 g_开启帧更新 = false;
//static uint16						     gJIT参数ID = 0;
//static std::mutex g_分配内存锁;

std::mutex C_节点树::g_分配内存锁;


bool	C_节点树::g_节点是否可编辑 = true;

C_StrKey分配器 C_节点树::g_函数名称分配;
C_StrKey分配器 C_节点树::G节点名称分配;
uint8          C_节点树::G_编译优化 = 0;


std::vector<void**> C_节点树::g_节点JIT参数;
std::vector<uint32> C_节点树::g_JIT一级参数删除记录;




static void on_GPU参数修改更新渲染器(struct S_板载缓存* buf) {
	f_render_刷新渲染(f_NodeCtx_get默认场景());
}



 
C_节点树::C_节点树(const std::wstring& idName) :m_更新方式(E_节点树更新方式::e_帧更新), m_当前场景(NULL), m_以删除(false) {
	m_IDName = idName;
	if (g_节点树.find(m_IDName) == g_节点树.end()) {
		g_节点树[m_IDName] = this;
	}
	m_ID = 0;


	m_父节点 = nullptr;
	m_树类型 = E_节点树类型::e_type_物体节点树;
	
	m_函数名称 = f_alloc_StrProp(nullptr, L"函数名称");
	m_函数名称.m_私有 = true;
	
	m_外部加载 = f_alloc_BoolProp(nullptr, L"外部加载");
	m_外部加载.m_私有 = true;
	f_prop_Bool(m_外部加载) = false;

	m_代码文件路径 = f_alloc_PathProp(nullptr, L"code");
	m_代码文件路径.m_私有 = true;

	m_编译方式 = f_alloc_EnumProp(nullptr, { {L"不编译", ""}, {L"LLVM", ""}, {L"DLL", ""}, }, L"编译方式");
	m_编译方式.m_私有 = true;
	f_prop_enum(m_编译方式) = 2;

	


	m_开始编译 = false;
	m_未保存或加载 = false;
	m_编译以准备好 = false;

	m_开启标记循环内部节点 = false;
	m_节点结构改变 = false;
	
	m_程序集 = 0;
	m_以编译 = E_节点树编译位标志::e_节点编译_重新编译;

	m_布局方向 = E_方向::e_纵向;


	
	{
		C_节点树::g_分配内存锁.lock();
		if (g_JIT一级参数删除记录.size()) {
			m_参数全局偏移 = g_JIT一级参数删除记录.back();
			g_节点JIT参数[m_参数全局偏移] = m_JIT二级参数.data();
			g_JIT一级参数删除记录.pop_back();
		}
		else {
			m_参数全局偏移 = g_节点JIT参数.size();
			g_节点JIT参数.push_back(m_JIT二级参数.data());
		}
		C_节点树::g_分配内存锁.unlock();
	}
}

C_节点树::~C_节点树() {
	if (m_程序集) {
		f_JIT_销毁(m_程序集, (E_JIT方式)f_prop_enum(m_编译方式));
		m_程序集 = 0;
	}

	m_节点树绑定的父节点.clear();

	f_prop_Release(m_函数名称);
	f_prop_Release(m_代码文件路径);


	{
		C_节点树::g_分配内存锁.lock();

		g_节点JIT参数[m_参数全局偏移] = nullptr;
		g_JIT一级参数删除记录.push_back(m_参数全局偏移);

		C_节点树::g_分配内存锁.unlock();
	}
}

C_节点树 * C_节点树::f_get节点树(const std::wstring& key) {
	if (g_节点树.find(key) != g_节点树.end()) {
		return g_节点树[key];
	}
	return nullptr;
}

std::string C_节点树::f_getName() {
	switch (m_树类型) {
		case E_节点树类型::e_type_着色节点树:
			return f_str_汉字字符串转拼音(m_IDName);
		default:
			break;
	}
	return f_WStringToString(m_IDName);
}

//void C_节点树::f_set更新方式(uint32 type) {
//}

void C_节点树::f_准备Update() {
	f_查找开始节点();

	if (m_节点结构改变) {
		S_光追后端::f_重置渲染帧记录();

		for (auto& node_p : m_Nodes) {
		//for (auto& it = m_Nodes.begin(); it != m_Nodes.end(); ++it) {
			//C_节点基类* node_p = *it;
			node_p->m_层 = 0xffffffff;
			node_p->m_区域父节点 = nullptr;
			node_p->m_标记区域 = false;

			switch (node_p->m_Type) {
				case E_节点类型::e_节点Type_循环迭代:
				case E_节点类型::e_节点Type_判断:
				case E_节点类型::e_节点Type_循环:
				case E_节点类型::e_节点Type_迭代:
					node_p->m_区域内节点.clear();
					break;
				default:
					break;
			}
		}


		if (m_程序集) {
			//f_JIT_销毁(m_程序集, m_编译方式);
			f_JIT_销毁(m_程序集, (E_JIT方式)f_prop_enum(m_编译方式));
			m_程序集 = 0;
		}
		m_以编译 = E_节点树编译位标志::e_节点编译_重新编译;
		f_计算节点层级();

		

		m_节点结构改变 = false;
	}

	f_准备帧Update();

}

void C_节点树::f_标记区域节点(C_节点基类* node) {
	uint32 num = node->f_get输入插座Num();

	if (node->m_标记区域) {
		//return;
	}
	node->m_标记区域 = true;

	//if (node->m_Type == E_节点类型::e_节点Type_循环尾) {
	//	return;
	//}
	
	for (uint32 i = 0; i < num; ++i) {
		auto* socket = node->f_get输入插座(i);
		auto link_nodes = socket->f_get链接到的输出插座节点();
		
		for (auto& 上层节点 : link_nodes) {
			if (上层节点->m_Type == E_节点类型::e_节点Type_循环尾) {
				continue;
			}

			f_标记区域节点(上层节点);
		}
	}
}

bool C_节点树::f_Update(uint32 层ID) {
	
	C_节点基类** nodes = m_层更新节点[层ID].data();
	uint32 num = m_层更新节点[层ID].size();
	std::vector<std::future<void>>	等待线程;

	uint8 是否中断 = 0;

	//更新当前层节点
	for (uint16 i = 0; i < num; ++i) {
		bool 可以更新 = nodes[i]->f_get输入插座(0)->f_getBool({0,0,0,0});
		//!层ID &&  (nodes[i]->f_get更新方式() == E_节点更新方式::e_节点更新_逐帧) ||
		if (可以更新) {
			if (m_开启帧更新 && nodes[i]->f_get更新方式() == E_节点更新方式::e_节点更新_逐帧) {
				goto To_第一层节点更新;
			}
			if (nodes[i]->f_get更新方式() == E_节点更新方式::e_节点更新_实时) {
				goto To_第一层节点更新;
			}
		}
		
		

		if (nodes[i]->f_需要更新() && 可以更新) {
To_第一层节点更新:
			//if (nodes[i]->m_并发) {
			if (false) {
				C_节点基类* p = nodes[i];
				等待线程.push_back( 
					std::async(std::launch::async, [&]() {
						p->f_update();
						p->f_set下层节点为需要更新();
						p->f_set是否要更新(false);
					}) 
				);

			}
			else {
				clock_t start, end;
				start = clock();

				//bool 中断 = false;
				bool 中断 = nodes[i]->f_update();

				nodes[i]->f_set下层节点为需要更新();
				nodes[i]->f_输入插座标记已读();

				if (中断) {
					是否中断 = 中断;
				}
				else {
					nodes[i]->f_set是否要更新(false);
				}

				end = clock();
				nodes[i]->m_耗时 = (end - start);

			}

			++(nodes[i]->m_更新时间);
		}

	}


	for(auto& t: 等待线程) t.wait();

	
	C_节点基类** 上一层_nodes = m_层更新节点[层ID].data();
	uint32 上一层_num = m_层更新节点[层ID].size();
	for (uint16 i = 0; i < 上一层_num; ++i) {
		if (上一层_nodes[i]->f_需要更新() && 上一层_nodes[i]->m_是否释放数据) {
			//上一层_nodes[i]->f_释放数据();
		}

		uint32 num = 上一层_nodes[i]->f_get输入插座Num();
		for (int32 socket_id = 0; socket_id < num; ++socket_id) {
			上一层_nodes[i]->f_get输入插座(socket_id)->m_有新数据 = false;
		}
	}
	
	
	return 是否中断;
}

std::string C_节点树::f_编译一层节点(uint32 层ID, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	C_节点基类** nodes = m_层更新节点[层ID].data();
	uint32 num = m_层更新节点[层ID].size();

	//m_以编译 = 1;
	std::string m_Code = "";
	//std::string 当前节点定义;
	for (uint16 i = 0; i < num; ++i) {
		//子节点输入输出节点父节点设置
		switch (nodes[i]->m_Type) {
		case E_节点类型::e_节点Type_函数:
		case E_节点类型::e_节点Type_几何:
		case E_节点类型::e_节点Type_循环迭代:
			break;
		}
		nodes[i]->m_编译成功 = true;

		m_Code += nodes[i]->f_编译(0, 声明, 定义, 释放);
		nodes[i]->f_set下层节点为需要更新();
	}

	return m_Code;
}

uint32 C_节点树::f_gen参数ID() {
	return m_JIT参数ID++;
}

void C_节点树::f_准备编译节点树() {
	//m_以编译 ^= E_节点树编译位标志::e_节点编译_外部调用;
	m_JIT参数ID = 0;
	//m_节点JIT参数.clear();
	m_JIT二级参数.clear();

	for (auto& node : m_Nodes) {
		auto* st = node->f_get子集树();
		switch (node->m_Type) {
		case E_节点类型::e_节点Type_循环迭代:
		case E_节点类型::e_节点Type_几何:
		case E_节点类型::e_节点Type_包:
		case E_节点类型::e_节点Type_函数:
			if (st->m_编译以准备好 == false) {
				st->m_编译以准备好 = true;
				m_节点结构改变 = true;
				st->f_准备编译节点树();

				
			}
			break;
		}
	}
}






void C_节点树::f_添加节点(C_节点基类* node) {
	if (m_Nodes.find(node) == m_Nodes.end()) {
		m_Nodes.insert(node);

		node->f_set所在节点树(this);
		node->f_更新上层节点(true);
		m_节点结构改变 = true;
	}
	
	node->f_setWName( G节点名称分配.f_Gen(node->f_getWName()) );
	m_层更新节点.clear();
}

void C_节点树::f_删除节点(C_节点基类* node) {
	if (m_Nodes.find(node) != m_Nodes.end()) {
		
		m_Nodes.erase(node);
		G节点名称分配.f_Move(node->f_getWName());
		
		node->f_解绑定子集节点树();
		node->f_更新上层节点(true);
		m_节点结构改变 = true;
	}

	m_层更新节点.clear();
}

uint32 C_节点树::f_getNodeNum() {
	return m_Nodes.size();
}

C_节点基类 * C_节点树::f_getNode(const std::string& key) {
	return nullptr;
}




void C_节点树::f_重置节点更新时间() {
}
void C_节点树::f_重置节点名称() {
	return;
}
void C_节点树::f_reset() {
}


C_节点树* C_节点树::f_拷贝() {
	C_节点树* newTree = f_getTree(L"");
	return newTree;
}

C_节点树* C_节点树::f_getThisTree() {
	switch (m_树类型) {
	case E_节点树类型::e_type_几何节点树:
	case E_节点树类型::e_type_函数节点树:
	//case S_节点树类型::e_type_循环节点树:
		return this;
	default:
		if(m_节点树绑定的父节点.size()) (*m_节点树绑定的父节点.begin())->f_getThis节点树();
		break;
	}
	return nullptr;
}









typedef struct {
	S_键值序列容器<std::string, C_节点基类*>*	nodes;
	C_节点树*		tree;
	uint32			sStart;
	uint32			sCount;
}S_开始节点查找参数;


void f_取头节点(S_开始节点查找参数* pNode) {
	//cout << "pNode = " << pNode->sCount << endl;

	std::vector<C_节点基类*> 头节点;
	C_节点基类** nodes = pNode->nodes->gData序列容器.data();
	for (uint16 i = pNode->sStart; i < pNode->sStart + pNode->sCount; ++i) {
		if (nodes[i]->f_get输入插座链接数量() == 0) {
			E_节点更新方式 更新方式 = nodes[i]->f_get更新方式();

			头节点.push_back(nodes[i]);
		}
	}

	pNode->tree->m_节点更新锁.lock();
	pNode->tree->m_开始节点.insert(pNode->tree->m_开始节点.end(), 头节点.begin(), 头节点.end());
	pNode->tree->m_节点更新锁.unlock();

	return;
}




void f_线程_取头节点(S_键值序列容器<std::string, C_节点基类*>* pNode, C_节点树* tree, std::mutex& 锁, uvec2 range) {
	//cout << "pNode = " << pNode->sCount << endl;
	std::vector<C_节点基类*> 头节点;
	C_节点基类** nodes = pNode->gData序列容器.data();
	for (uint16 i = range.x; i < range.y; ++i) {
		if (nodes[i]->f_get输入插座链接数量() == 0) {
			E_节点更新方式 更新方式 = nodes[i]->f_get更新方式();

			头节点.push_back(nodes[i]);
		}
	}

	锁.lock();
	tree->m_开始节点.insert(tree->m_开始节点.end(), 头节点.begin(), 头节点.end());
	锁.unlock();
	return;
}





void C_节点树::f_查找开始节点() {
	m_开始节点.clear();

	bool 更新头节点 = false;
	if (m_节点树绑定的父节点.size()) {
		更新头节点 = true;
	}
	
	uint32 num = m_Nodes.size();
	if (num > 512) {
		std::mutex 锁;
		Concurrency::parallel_for_each(m_Nodes.begin(), m_Nodes.end(), [&](C_节点基类* e) {
			if (e->f_get输入插座链接数量() == 0) {
				if (e->f_get更新方式() == E_节点更新方式::e_节点更新_实时) {
					e->f_set是否要更新(true);
				}

				锁.lock();
				m_开始节点.push_back(e);
				锁.unlock();
			}
		});
	}
	else {
		for (auto& e : m_Nodes) {
			if (e->f_get输入插座链接数量() == 0) {
				if (e->f_get更新方式() == E_节点更新方式::e_节点更新_实时 || 更新头节点) {
					e->f_set是否要更新(true);
				}
				m_开始节点.emplace_back(e);
			}
		}
	}
}

void C_节点树::f_准备帧Update() {
	if (m_层更新节点.size() <= 0) return;

	uint32 num = m_层更新节点[0].size();
	auto* node_p = m_层更新节点[0].data();

#pragma omp parallel for num_threads(2)
	for (int32 i = 0; i < num; ++i) {
		E_节点更新方式 方式 = node_p[i]->f_get更新方式();
		if (方式 == E_节点更新方式::e_节点更新_实时) {
			node_p[i]->f_set是否要更新(true);
		}
		if (S_节点数据::g_开启节点帧更新 && 方式 == E_节点更新方式::e_节点更新_逐帧) {
			node_p[i]->f_set是否要更新(true);
		}
	};

}






void C_节点树::f_计算节点层级() {
	//将层ID全部标记到最大
	//Concurrency::parallel_for_each(m_Nodes.begin(), m_Nodes.end(), [&](C_节点基类* node_p) {
	//	if (node_p->m_Type == E_节点类型::e_节点Type_循环尾) {
	//		f_标记区域节点(node_p);
	//	}
	//});
	for (auto& e : m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_循环尾) {
			f_标记区域节点(e);
		}
	}
	

	std::vector<C_节点基类*> 当前层 = m_开始节点;

	m_层更新节点.clear();
	for (int32 depth = 0; ; ++depth) {
		m_层更新节点.push_back(当前层);

		f_推进节点层级计算(当前层, depth);
		if (当前层.size() == 0) {
			break;
		}
	}
}

void C_节点树::f_推进节点层级计算(std::vector<C_节点基类*>& 当前层节点, uint32 depth) {
	C_节点基类** nodes = 当前层节点.data();
	uint32 num = 当前层节点.size();


//#pragma omp parallel for
	for (uint32 i = 0; i < num; ++i) {
		nodes[i]->f_标记层级结构需更新(false);
		nodes[i]->m_层 = depth;
	}


	std::vector<C_节点基类*> 下层要标记节点;
	下层要标记节点.reserve(32);
	for (uint32 i = 0; i < num; ++i) {
		std::vector<C_节点基类*> 当前节点的下层节点;
		auto& node = nodes[i];
		nodes[i]->f_get下层节点(当前节点的下层节点);

		

		uint32 下层节点数量 = 当前节点的下层节点.size();
		if (下层节点数量) {
			for (uint32 j = 0; j < 下层节点数量; ++j) {
				//迭代下层节点的所有输入插座 取得输入插座连接到的节点  判断层ID是否已设置
				
				switch (node->m_Type) {
				case E_节点类型::e_节点Type_判断:
				case E_节点类型::e_节点Type_迭代:
				case E_节点类型::e_节点Type_循环: {
					当前节点的下层节点[j]->m_区域父节点 = node;
					break;
				}
				
				default:
					if (当前节点的下层节点[j]->m_标记区域 && node->m_区域父节点) {
						//区域尾节点不包含到当前节点区域 而是在当前节点父节点区域中
						if (E_节点类型::e_节点Type_循环尾 == node->m_Type) {
							if (node->m_区域父节点->m_区域父节点) {
								当前节点的下层节点[j]->m_区域父节点 = node->m_区域父节点->m_区域父节点;
							}
						}
						else {
							当前节点的下层节点[j]->m_区域父节点 = node->m_区域父节点;
						}
					}
					break;
				}
				
				auto* 区域节点 = 当前节点的下层节点[j]->m_区域父节点;
				if (区域节点) {
					区域节点->m_区域内节点.insert(当前节点的下层节点[j]);
					//区域节点 = 区域节点->m_区域父节点;
				}
				

				bool 是否有中间层 = false;
				uint32 输入插座数量 = 当前节点的下层节点[j]->f_get输入插座Num();
				for (uint32 k = 0; k < 输入插座数量; ++k) {
					//判断当前层下层节点链接到的上层节点是否是当前层的
					//        ____1---2
					//        |
					//    0---|---1---2
					//        |
					//    0___|---2---3
					//     |      |
					//     |--1---|
					//        |
					//        |___2---3
					//

					auto* inSocket = 当前节点的下层节点[j]->f_get输入插座(k);

					

					//if (inSocket->f_is回写()) {
						//continue;
					//}

					auto 当前下层的上层节点 = inSocket->f_get链接到的输出插座节点();

					for (auto 上层节点 : 当前下层的上层节点) {
						if (上层节点->m_层 > depth) {
							是否有中间层 = true;
							break;
						}

					}
				}

				if (是否有中间层 == false) {
					下层要标记节点.emplace_back(当前节点的下层节点[j]);
				}
			}
		}
	}


	//移除重复元素
	sort(下层要标记节点.begin(), 下层要标记节点.end());
	下层要标记节点.erase(unique(下层要标记节点.begin(), 下层要标记节点.end()), 下层要标记节点.end());

	当前层节点 = 下层要标记节点;

}






C_节点树* f_node_Create节点树(bool isRootNode, std::wstring name) {
	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_根节点树.push_back(t);
	}
	t->m_树类型 = E_节点树类型::e_type_物体节点树;


	S_MapPtrItem item;
	item.m_Ptr = t;
	//item.m_Str = &(t->m_IDName);
	item.m_Str = t->m_IDName;
	S_节点数据::g_物体节点树.push_back(item);

	return t;
}

C_节点树* f_node_Create包节点树(bool isRootNode, std::wstring name) {
	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_根节点树.push_back(t);
	}
	t->m_树类型 = E_节点树类型::e_type_包节点树;

	S_MapPtrItem item;
	item.m_Ptr = t;
	//item.m_Str = &(t->m_IDName);
	item.m_Str = t->m_IDName;
	S_节点数据::g_包节点树.push_back(item);

	return t;
}

C_节点树* f_node_Create渲染节点树(bool isRootNode, std::wstring name) {

	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_渲染根节点树.push_back(t);
	}
	t->m_树类型 = E_节点树类型::e_type_渲染节点树;

	S_MapPtrItem item;
	item.m_Ptr = t;
	//item.m_Str = &(t->m_IDName);
	item.m_Str = t->m_IDName;
	S_节点数据::g_渲染节点树.push_back(item);

	return t;
}

C_节点树* f_node_Create几何节点树(bool isRootNode, std::wstring name) {
	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_根节点树.push_back(t);
	}
	t->m_树类型 = E_节点树类型::e_type_几何节点树;
	t->m_布局方向 = E_方向::e_横向;

	S_MapPtrItem item;
	item.m_Ptr = t;
	//item.m_Str = &(t->m_IDName);
	item.m_Str = t->m_IDName;

	f_prop_Str(t->m_函数名称) = C_节点树::g_函数名称分配.f_Gen(L"fun_geom_");

	S_节点数据::g_几何节点树.push_back(item);

	return t;
}

C_节点树* f_node_Create函数节点树(bool isRootNode, std::wstring name) {
	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_根节点树.push_back(t);
	}

	t->m_树类型 = E_节点树类型::e_type_函数节点树;
	t->m_布局方向 = E_方向::e_横向;

	S_MapPtrItem item;
	item.m_Ptr = t;
	//item.m_Str = &(t->m_IDName);
	item.m_Str = t->m_IDName;

	f_prop_Str(t->m_函数名称) = C_节点树::g_函数名称分配.f_Gen(L"fun_");
	//S_节点数据::g_物体节点树.push_back(item);
	S_节点数据::g_函数节点树.push_back(item);
	return t;
}

C_节点树* f_node_Create循环节点树(bool isRootNode, std::wstring name) {
	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_根节点树.push_back(t);
	}
	t->m_树类型 = E_节点树类型::e_type_循环节点树;

	S_MapPtrItem item;
	item.m_Ptr = t;
	//item.m_Str = &(t->m_IDName);
	item.m_Str = t->m_IDName;
	S_节点数据::g_物体节点树.push_back(item);

	return t;
}

C_节点树* f_node_Create材质节点树(bool isRootNode, std::wstring name) {
	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_根节点树.push_back(t);
	}
	t->m_树类型 = E_节点树类型::e_type_材质节点树;
	t->m_布局方向 = E_方向::e_横向;

	S_MapPtrItem item;
	item.m_Ptr = t;
	item.m_Str = t->m_IDName;
	//item.m_Str = &(t->m_IDName);

	f_prop_Str(t->m_函数名称) = C_节点树::g_函数名称分配.f_Gen(L"fun_material_");
	f_prop_Bool(t->m_外部加载) = false;

	S_节点数据::g_材质节点树.push_back(item);
	return t;
}

C_节点树* f_node_Create着色节点树(bool isRootNode, std::wstring name) {
	C_节点树* t = new C_节点树(S_节点数据::g_节点树名称分配器.f_Gen(name));

	if (isRootNode) {
		S_节点数据::g_根节点树.push_back(t);
	}
	t->m_树类型 = E_节点树类型::e_type_着色节点树;
	t->m_布局方向 = E_方向::e_横向;

	S_MapPtrItem item;
	item.m_Ptr = t;
	//item.m_Str = &(t->m_IDName);
	item.m_Str = t->m_IDName;
	t->m_ID = S_节点数据::g_着色器ID分配器.f_Gen();


	f_prop_Str(t->m_代码文件路径) = f_StringToWString(S_引擎配置::m_3D着色器文件根路径);
	f_prop_Str(t->m_函数名称) = C_节点树::g_函数名称分配.f_Gen(L"fun_shader_");
	f_prop_Bool(t->m_外部加载) = false;
	
	auto s = f_prop_Str(t->m_函数名称);


	S_节点数据::g_着色节点树.push_back(item);
	return t;
}

C_节点树* f_node_Create纹理节点树(bool isRootNode, std::wstring name) {

	return nullptr;
}

void f_NT_销毁节点(C_节点树* t) {
	for (auto& e : t->m_Nodes) {
		uint32 snum = e->f_get输入插座Num();
		for (uint32 i = 0; i < snum; ++i) {
			e->f_get输入插座(i)->f_断开输出链接(nullptr);
		}
	}

	for (auto& e : t->m_Nodes) {
		if (e->m_Type != E_节点类型::e_节点Type_函数) {
			delete e;
		}
	}

	t->m_Nodes.clear();
}

void f_NT_Release(C_节点树* t) {
	switch (t->m_树类型) {
	case E_节点树类型::e_type_包节点树: {
		uint32 num = S_节点数据::g_包节点树.size();
		for (uint32 i = 0; i < num; ++i) {
			if (S_节点数据::g_包节点树[i].m_Ptr == t) {
				S_节点数据::g_包节点树.erase(S_节点数据::g_包节点树.begin() + i);
				break;
			}
		}
		break;
	}
	default:
		break;
	}

	//for (auto& e : t->m_Nodes) {
	//	uint32 snum = e->f_get输入插座Num();
	//	for (uint32 i = 0; i < snum; ++i) {
	//		e->f_get输入插座(i)->f_断开输出链接(nullptr);
	//	}
	//}
	//for (auto& e : t->m_Nodes) {
	//	delete e;
	//}
	//t->m_Nodes.clear();
	delete t;
	
}


void f_node_帧更新(bool t) {
	S_节点数据::g_开启节点帧更新 = t;
}

bool f_node_帧是否更新() {
	return S_节点数据::g_开启节点帧更新;
}

void f_NT_准备更新开始节点(C_节点树* tree) {
	uint32 num = tree->m_层更新节点.size();
	if (!num) return;

	if (f_node_帧是否更新()) {
		for (auto& n : tree->m_层更新节点[0]) {
			if (n->f_get更新方式() == E_节点更新方式::e_节点更新_实时) {
				n->f_set是否要更新(true);
			}
		}
	}
}

void f_NT_刷新全局参数(C_节点树* tree) {
	C_节点树::g_分配内存锁.lock();

	C_节点树::g_节点JIT参数[tree->m_参数全局偏移] = tree->m_JIT二级参数.data();

	C_节点树::g_分配内存锁.unlock();
}

void f_NT_冻结节点(C_节点基类* rn, bool 冻结) {
	//tree->m_层更新节点.size();
	uint32 num = rn->f_get输入插座Num();
	for (uint32 i = 0; i < num; ++i) {
		auto 上层节点 = rn->f_get输入插座(i)->f_get链接到的输出插座节点();

		for (auto& e : 上层节点) {
			if (e->m_越过更新 == !冻结) {
				e->m_越过更新 = 冻结;
				f_NT_冻结节点(e, 冻结);
			}
		}
	}

}

void f_NT_预处理冻结节点(C_节点树* tree) {
	tree->f_准备Update();
	for (auto& e : tree->m_Nodes) {
		if (e->m_冻结数据) {
			f_NT_冻结节点(e, e->m_冻结数据);
		}
	}
}

bool f_NT_StepUpdate节点(C_节点树* tree, bool 帧更新) {
	//return true;
	bool 是否中断 = false;
	tree->f_准备Update();

	tree->m_开启帧更新 = 帧更新;

	uint32 num = tree->m_层更新节点.size();
	for (uint32 i = 0; i < num; ++i) {
		if (tree->f_Update(i)) {
			tree->m_中断层 = i;
			是否中断 = true;
			break;
		}
	}

	return !是否中断;
}

bool f_NT_编译节点(C_节点基类* rn, std::string path, bool 编译成动态链接库) {
	bool 是否中断 = false;
	C_节点树* tree = rn->f_get子集树();

	//if (f_file_文件是否存在(path) == false) {
		//f_file_路径是否为目录()
		//path = S_节点数据::g_工程文件临时路径 + path;
		//return false;
	//}
	FILE* f = fopen(path.c_str(), "w");
	if (f) {
		std::string 声明, code, 释放;
		std::vector<std::string> 定义;

		code += rn->f_编译(0, 声明, 定义, 释放);


		std::string hpp;
		//hpp += "#include \"vector\" \n ";
		hpp = "#define DEF_JIT \n";

		hpp += "#include <basic_def.h>\n";
		
		hpp += "\n";
		hpp += f_代码构建_预定义类型();
		hpp += "\n";

		hpp += "#include <basic_vec.h>\n";
		
		hpp += "#include <texture.h>\n";
		hpp += "#include <shader_std.h>\n";
		hpp += "#include <polygon.h>\n";
		
		
		//hpp += DEF_S(CORE_ARRAY_HANDLE(S_UI32Array2D, S_UI32Array*));
		hpp += "\n";

		hpp += f_代码构建_函数指针();
		hpp += "\n";
		hpp += f_代码构建_JIT函数指针初始化();
		hpp += "\n";
		
		hpp += "#include <basic_common_function.h>\n";
		hpp += "#include <vec_conversion.h>\n";
		hpp += "#include <mesh_container.h>\n";

		f_代码构建_内联函数保存到文件();
		hpp += "#include <Inline_fun.h>\n";
		

		hpp += 声明;
		for (auto& e : 定义) {
			hpp += e;
		}
		hpp += code;

		
		//hpp = f_StringToUTF8(hpp);
		f_file_保存文本(f, hpp);
		fclose(f);

		


		std::string 源文件路径 = f_file_get路径(path);
		std::string 输出文件路径 = 源文件路径 + f_file_取无后缀文件名(path);


		std::string includePath = " -I ";
#ifdef 预定义_最终输出
		includePath += (S_引擎配置::g_程序路径) + "include";

#else
		includePath += S_引擎配置::g_程序路径 + "include";

#endif // 预定义_最终输出
		std::cout<<"includePath:"<< includePath<<std::endl;
		includePath += " -I \"" + S_节点数据::g_工程文件节点代码路径 + "\"";

		//std::string 编译参数 = "\"" + S_节点数据::g_编译器路径 + "\"";
		std::string 编译参数 = S_节点数据::g_编译器路径;
		

		switch (f_prop_enum(tree->m_编译方式)) {
		case E_JIT方式::e_jit_dll: {
			输出文件路径 += ".ex";
			输出文件路径 = "\"" + 输出文件路径 + "\"";

			编译参数 += "clang.exe -o3 -fopenmp -shared -Wl " + path + " -o " + 输出文件路径 + includePath;
			//编译参数 += "clang.exe -g -o3 -shared -Wl " + path + " -o " + 输出文件路径 + includePath;
			break;
		}
		case E_JIT方式::e_jit_llvm: {
			输出文件路径 += ".bc";
			输出文件路径 = "\"" + 输出文件路径 + "\"";

			编译参数 += "clang.exe -o3 -fopenmp -emit-llvm " + path + " -c -o " + 输出文件路径 + includePath;
			break;
		}
		}

		std::cout << "编译文件: " << 输出文件路径 << std::endl;
		
		//err = system("D:/U/DEV/_LLVM/bin/clang.exe -o3 -emit-llvm d:/03.hpp -c -o d:/03.bc");
		int32 err = system(编译参数.c_str());
		//int32 err = _wsystem(编译参数.c_str());
		std::cout << "err:" << err << std::endl;
		if (err) {
			return false;
		}
		
	}
	
	return true;
}

std::string f_NT_编译节点树(C_节点树* tree, std::vector<std::string>& 定义, std::string& 声明) {
	std::string code;
	tree->f_准备Update();

	tree->m_开启帧更新 = true;
	//tree->m_以编译 = 1;

	std::string 释放;
	uint32 num = tree->m_层更新节点.size();
	for (uint32 i = 0; i < num; ++i) {
		code += tree->f_编译一层节点(i, 声明, 定义, 释放);
	}
	code += 释放;

	C_节点树::g_节点JIT参数[tree->m_参数全局偏移] = tree->m_JIT二级参数.data();
	return code;
}

uint64 f_NT_初始化函数接口(uint64 程序集, std::string 函数名称, E_JIT方式 方式) {
	uint64 m_函数指针 = f_JIT_取函数指针(程序集, 函数名称, 方式);

	auto 函数初始化指针 = (f_JIT_接口函数指针初始化)f_JIT_取函数指针(程序集, "f_fnPtr_init", 方式);
	switch (方式) {
		case E_JIT方式::e_jit_dll:
			if (函数初始化指针) {
				函数初始化指针(f_代码构建_取参数函数指针().data());
			}
			else {
				return 0;
			}
			break;
		default: {
			static bool 函数指针初始化 = true;
			if (函数指针初始化) {
				f_JIT_添加全局变量(S_JIT_函数指针名称::g函数指针名称, f_代码构建_取参数函数指针());
			}
			函数指针初始化 = false;
			break;
		}
	}
	return m_函数指针;
}


bool f_NT_是否内联调用(C_节点基类* node) {
	switch (node->f_get所在节点树()->m_树类型) {
	case E_节点树类型::e_type_几何节点树:
	case E_节点树类型::e_type_函数节点树:
	case E_节点树类型::e_type_材质节点树:
	case E_节点树类型::e_type_着色节点树:
		return true;
	default:
		for (auto& e : node->f_get所在节点树()->m_节点树绑定的父节点) {
			if (f_NT_是否内联调用(e)) {
				return true;
			}
		}
		break;
	}
	return false;
}

uint8* f_NT_序列化节点组数据(C_节点树* tree, S_文件块& 文件块) {
	return nullptr;
}
void f_NT_读取节点组数据(C_节点树* tree) {

}
void f_NT_保存节点组数据(C_节点树* tree) {

}

void f_NT_构建框节点依赖结构(C_节点基类* 当前框节点, std::vector<C_节点基类*>& 框包含节点, std::map<std::wstring, C_节点基类*>& 新节点集) {
	当前框节点->m_框包含节点.reserve(框包含节点.size());
	for (auto& node : 框包含节点) {
		C_节点基类* 节点 = 新节点集[node->f_getWName()];
		if (节点) {
			当前框节点->m_框包含节点.push_back(节点);
			节点->m_框节点 = 当前框节点;

			if (E_节点类型::e_节点Type_框 == node->m_Type) {
				f_NT_构建框节点依赖结构(节点, node->m_框包含节点, 新节点集);
			}
		}
	}
}





std::string f_代码构建_属性变量(S_Props& prop, C_节点树* rt) {
	std::string code;

	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		switch (prop.m_Type) {
		case E_值类型::e_Type_F32:
			code = "f32_GParam.f32Ptr[" + f_整数值转字符串(prop.m_GPU缓存[0].m_Mem.m_偏移) + "]"; break;
		case E_值类型::e_Type_I32:
		case E_值类型::e_Type_Enum:
			code = "i32_GParam.i32Ptr[" + f_整数值转字符串(prop.m_GPU缓存[0].m_Mem.m_偏移) + "]"; break;

		case E_值类型::e_Type_Vec3:
			code = "vec3_GParam.vec3Ptr[" + f_整数值转字符串(prop.m_GPU缓存[0].m_Mem.m_偏移) + "]"; break;

		case E_值类型::e_Type_2D曲线:
			code = "uvec2_GParam.uvec2Ptr[" + f_整数值转字符串(prop.m_GPU缓存[1].m_Mem.m_偏移) + "]"; break;
			break;
		default:
			break;
		}

		break;
	}

	default: {
		rt->g_分配内存锁.lock();
		auto& JIT参数 = rt->m_JIT二级参数;
		uint32 常量ID = JIT参数.size();

		switch (prop.m_Type) {
		case E_值类型::e_Type_Enum: {
			JIT参数.push_back(&(f_prop_enum(prop)));
			break;
		}
		case E_值类型::e_Type_2D曲线: {
			JIT参数.push_back(f_prop_2DCurve(prop));
			break;
		}
		default:
			JIT参数.push_back(prop.m_Value);
			break;
		}
		//C_节点树::g_节点JIT参数[rt->m_参数全局偏移] = rt->m_JIT二级参数.data();
		rt->g_分配内存锁.unlock();

		code = "(*(" + f_node_getDataTypeName(prop.m_Type) + "*)(g参数[" + f_整数值转字符串(rt->m_参数全局偏移) + "][" + f_整数值转字符串(常量ID) + "]))";

		break;
	}
	}

	return code;
}

std::string f_代码构建_变量(C_节点树* rt, void* data, E_值类型 type) {
	std::string code;

	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		switch (type) {
		case E_值类型::e_Type_F32:
			return f_浮点数值转字符串(*(float32*)data);
		case E_值类型::e_Type_I32:
			return f_整数值转字符串(*(int32*)data);
		case E_值类型::e_Type_UI32:
			return f_整数值转字符串(*(uint32*)data);

		case E_值类型::e_Type_Vec3_1D:
		case E_值类型::e_Type_Vec3:
			code = "vec3(";
			code += f_浮点数值转字符串((*(vec3*)data).x) + ", ";
			code += f_浮点数值转字符串((*(vec3*)data).y) + ", ";
			code += f_浮点数值转字符串((*(vec3*)data).z) + ")";
			return code;

		case E_值类型::e_Type_Vec4:
			code = "vec4(";
			code += f_浮点数值转字符串((*(vec4*)data).x) + ", ";
			code += f_浮点数值转字符串((*(vec4*)data).y) + ", ";
			code += f_浮点数值转字符串((*(vec4*)data).z) + ", ";
			code += f_浮点数值转字符串((*(vec4*)data).w) + ")";
			return code;

		default:
			break;
		}

		break;
	}

	default:
		//auto& JIT参数 = rt->m_节点JIT参数;
		auto& JIT参数 = rt->m_JIT二级参数;
		uint32 常量ID = JIT参数.size();

		JIT参数.push_back(data);
		C_节点树::g_节点JIT参数[rt->m_参数全局偏移] = rt->m_JIT二级参数.data();

		code = "(*(" + f_node_getDataTypeName(type) + "*)(" + DEF_S(DEF_编译全局可调参数名称) + "[" + f_整数值转字符串(rt->m_参数全局偏移) + "][" + f_整数值转字符串(常量ID) + "]))";
		//code = "(*(" + f_node_getDataTypeName(type) + "*)(g参数[" + f_整数值转字符串(常量ID) + "]))";
		break;
	}

	return code;
}

std::string f_代码构建_插座变量数组数量(C_插座基类& socket, std::string& name, int32 loc) {
	std::string code;

	name += "数组数量";
	std::string type;
	switch (socket.m_Type) {
	case E_值类型::e_Type_Vec3_Array1D:
		code = "uint32 " + name + " = f_JIT_Fun_vec3_size(" + socket.f_getCode(loc) + ");\n";
		break;
	
	//case E_值类型::e_Type_F32_1D: type = "float32"; break;
	case E_值类型::e_Type_多边形边: type = "S_边";
		code = "uint32 " + name + " = " + DEF_S(f_多边形_边数量)"(" + socket.f_getCode(loc) + ");\n";
		break;
	case E_值类型::e_Type_Mat4X4_1D:
		code = "uint32 " + name + " = " + f_代码构建_Array数组数量(socket.f_getCode(loc)) + ";\n";
		break;

	case E_值类型::e_Type_F32_1D:
	case E_值类型::e_Type_I8_1D:
	case E_值类型::e_Type_I32_1D:

	case E_值类型::e_Type_UI32_1D:
	case E_值类型::e_Type_UI32_2D:

	case E_值类型::e_Type_Vec2_1D:

	case E_值类型::e_Type_Vec3_1D:
	case E_值类型::e_Type_Vec3_2D:

	case E_值类型::e_Type_Vec4_1D:

	case E_值类型::e_Type_iVec2_1D:

	case E_值类型::e_Type_iVec3_1D:
	case E_值类型::e_Type_iVec3_2D:

	case E_值类型::e_Type_uVec2_1D:
	case E_值类型::e_Type_uVec3_1D:
	
	case E_值类型::e_Type_多边形边1D:
	case E_值类型::e_Type_多边形元素:
	case E_值类型::e_Type_多边形元素1D:
		code = "uint32 " + name + " = (" + socket.f_getCode(loc) + "->count);\n";
		break;

	default:
		return "uint32 " + name + " = 0;\n";
		break;
	}

	return code;
}




void f_代码构建_输入输出节点参数(C_节点基类* rn, std::vector<C_节点基类*>& m_InNodes, const std::vector<C_节点基类*>& m_OutNudes) {
	uint32 inNum = 0;
	for (auto& e : m_InNodes) {
		inNum = e->f_get输出插座Num();

		for (uint32 i = 0; i < inNum; ++i) {
			//auto* socket = f_get输入插座(i);
			auto* socket = rn->f_get输入插座(i);

			e->f_get输出插座(i)->f_setCode(f_代码构建_节点树输入输出变量引用(socket->m_Type, i));
		}
	}

	for (auto& e : m_OutNudes) {
		uint32 outNum = e->f_get输入插座Num();

		for (uint32 i = 0; i < outNum; ++i) {
			std::string 函数参数名称 = f_代码构建_节点树输出变量名称(e, i);
			auto* socket = rn->f_get输出插座(i);

			rn->f_get输出插座(i)->f_setCode(f_代码构建_节点树输入输出变量引用(socket->m_Type, i + inNum));
		}
	}
}



void f_构建代码_分配渲染器GPU属性变量(S_Props& prop) {
	switch (prop.m_Type) {
	case E_值类型::e_Type_F32:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_F32动态属性, 1);
		break;
	case E_值类型::e_Type_Enum:
	case E_值类型::e_Type_I32:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_I32动态属性, 1);
		break;
	case E_值类型::e_Type_Vec2:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_Vec2动态属性, 1);
		break;
	case E_值类型::e_Type_Vec3:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_Vec3动态属性, 1);
		break;

	case E_值类型::e_Type_uVec2:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_UVec2动态属性, 1);
		break;
	case E_值类型::e_Type_uVec3:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_UVec3动态属性, 1);
		break;
	case E_值类型::e_Type_uVec4:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_UVec4动态属性, 1);
		break;

	case E_值类型::e_Type_2D曲线:
		prop.m_GPU缓存[0] = f_buf_alloc(S_全局缓存::m_采样曲线属性, 2);
		prop.m_GPU缓存[1] = f_buf_alloc(S_全局缓存::m_UVec2动态属性, 1);
		break;
	default:
		return;
	}
	
	prop.m_GPU缓存[0].m_Buf->m_Update = on_GPU参数修改更新渲染器;
}

void f_构建代码_释放渲染器GPU属性变量(S_Props& prop) {
	f_buf_erase(prop.m_GPU缓存[0]);
	/*switch (prop.m_Type) {
	case E_值类型::e_Type_F32:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_F32动态属性, prop.m_GPU缓存);
		break;
	case E_值类型::e_Type_Enum:
	case E_值类型::e_Type_I32:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_I32动态属性, prop.m_GPU缓存);
		break;
	case E_值类型::e_Type_Vec2:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_Vec2动态属性, prop.m_GPU缓存);
		break;
	case E_值类型::e_Type_Vec3:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_Vec3动态属性, prop.m_GPU缓存);
		break;
	default:
		break;
	}*/
	prop.m_GPU缓存[0].m_Buf = nullptr;
}

void f_构建代码_分配渲染器GPU插座变量(C_插座基类& socket) {
	switch (socket.m_Type) {
	case E_值类型::e_Type_F32:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_F32动态属性, 1);
		break;
	case E_值类型::e_Type_I32:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_I32动态属性, 1);
		break;
	case E_值类型::e_Type_Vec2:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_Vec2动态属性, 1);
		break;
	case E_值类型::e_Type_Vec3_1D:
	case E_值类型::e_Type_Vec3:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_Vec3动态属性, 1);
		break;

	case E_值类型::e_Type_uVec2:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_UVec2动态属性, 1);
		break;
	case E_值类型::e_Type_uVec3:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_UVec3动态属性, 1);
		break;
	case E_值类型::e_Type_uVec4:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_UVec4动态属性, 1);
		break;

	case E_值类型::e_Type_纹理:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_Vec3动态属性, 1);
		break;

	case E_值类型::e_Type_Mat4X4:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_Mat44动态属性, 1);
		break;

	case E_值类型::e_Type_2D曲线:
		socket.m_GPU缓存 = f_buf_alloc(S_全局缓存::m_采样曲线属性, 2);
		break;

	default:
		return;
	}
	socket.m_GPU缓存.m_Buf->m_Update = on_GPU参数修改更新渲染器;
	//socket.m_GPU缓存->m_Update = on_GPU参数修改更新渲染器;
}

void f_构建代码_释放渲染器GPU插座变量(C_插座基类& socket) {
	f_buf_erase(socket.m_GPU缓存);
	/*switch (socket.m_Type) {
	case E_值类型::e_Type_F32:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_F32动态属性, socket.m_GPU内存偏移);
		break;
	case E_值类型::e_Type_I32:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_I32动态属性, socket.m_GPU内存偏移);
		break;
	case E_值类型::e_Type_Vec2:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_Vec2动态属性, socket.m_GPU内存偏移);
		break;
	case E_值类型::e_Type_Vec3:
		f_buf_galloc(f_NodeCtx_get默认场景()->m_光追后端->m_Vec3动态属性, socket.m_GPU内存偏移);
		break;
	default:
		break;
	}*/
}





